<?php

namespace Common\Lib;

class Relation
{
    public static function belongsTo($list, $relation_model, $foreign_key, $key, $relation_name, $callback = null)
    {
        $keys = array_column($list, $foreign_key);

        $_list = D($relation_model)->select($keys);
        $_list = array_column($_list, null, $key);

        foreach ($list as $index => $item) {
            $_relation = isset($_list[$item[$foreign_key]]) ? $_list[$item[$foreign_key]] : null;
            // add relation data
            if (isset($callback) && is_callable($callback)) {
                $_relation = call_user_func($callback, $_relation);
            }
            $list[$index][$relation_name] = $_relation;
        }

        return $list;
    }

    public static function hasMany($list, $relation_model, $key, $foreign_key, $relation_name, $callback = null)
    {
        if (empty($list)) return $list;

        $keys = array_column($list, $key);

        $map[$foreign_key] = array('in', implode(',', $keys));

        $_list  = D($relation_model)->where($map)->select();
        $__list = array();
        foreach ($_list as $item) {
            $__list[$item[$foreign_key]][] = $item;
        }
        unset($_list);

        foreach ($list as $index => $item) {
            $_relation = isset($__list[$item[$key]]) ? $__list[$item[$key]] : array();
            if (is_callable($callback)) {
                $_relation = call_user_func($callback, $_relation);
            }
            // add relation data
            $list[$index][$relation_name] = $_relation;
        }

        return $list;
    }

    public static function hasManyLimit($limit, $list, $relation_model, $key, $foreign_key, $relation_name, $showuser = false)
    {
        $_uids     = array();
        $countname = $relation_name . '_count';

        foreach ($list as $index => $item) {
            $_list = D($relation_model)->where(array($foreign_key => $item[$key]))->limit($limit)->select();
            if ($_list && $showuser === true) {
                $_uids = array_merge($_uids, array_column($_list, 'uid'));
            }
            $list[$index][$relation_name] = $_list;
            $list[$index][$countname]     = D($relation_model)->where(array($foreign_key => $item[$key]))->count();
        }

        if ($showuser === true) {
            $ulist = Relation::fill_users($_uids);
            foreach ($list as $index => $item) {
                foreach ($item[$relation_name] as $key => $val) {
                    $list[$index][$relation_name][$key]['user'] = $ulist[$val['uid']];
                }
            }
        }

        return $list;
    }

    /**
     * @param $uids
     *
     * @return array|mixed
     */
    private static function fill_users($uids)
    {
        $uids  = is_array($uids) ? implode(',', $uids) : $uids;
        $ulist = M('User')->select($uids);
        $ulist = array_column($ulist, null, 'uid');
        $ulist = array_map(function ($user) {
            $fill_user = D('User')->auto_user_fill($user);
            $user      = array_merge($user, $fill_user);
            return $user;
        }, $ulist);
        return $ulist;
    }
}